Option Strict Off
Option Explicit On
Module ChromaKeying
	'This module handles all the chroma keying functions
	
	Public Threashold As Integer
	Public Feather As Integer
	Public WhiteLimit As Integer
	Public BlackLimit As Integer
	Dim Fiddle As Integer 'This value is used to fiddle the slider values, it enables the user to obtain the values at the end of the sliders more easily
	
	
	Private Structure BITMAPINFOHEADER '40 bytes
		Dim biSize As Integer
		Dim biWidth As Integer
		Dim biHeight As Integer
		Dim biPlanes As Short
		Dim biBitCount As Short
		Dim biCompression As Integer
		Dim biSizeImage As Integer
		Dim biXPelsPerMeter As Integer
		Dim biYPelsPerMeter As Integer
		Dim biClrUsed As Integer
		Dim biClrImportant As Integer
	End Structure
	
	Private Structure RGBQUAD
		Dim rgbBlue As Byte
		Dim rgbGreen As Byte
		Dim rgbRed As Byte
		Dim rgbReserved As Byte
	End Structure
	
	Dim Red_Source As Integer
	Dim Green_Source As Integer
	Dim Blue_Source As Integer
	
	Dim Alpha As Integer
	Dim InvAlpha As Integer
	
	Private Structure BITMAPINFO
		Dim bmiHeader As BITMAPINFOHEADER
		Dim bmiColors As RGBQUAD
	End Structure
	
	Private bitmap_info As BITMAPINFO
	
	'UPGRADE_WARNING: Structure BITMAPINFO may require marshalling attributes to be passed as an argument in this Declare statement. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="C429C3A5-5D47-4CD9-8F51-74A1616405DC"'
	'UPGRADE_ISSUE: Declaring a parameter 'As Any' is not supported. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="FAE78A8D-8978-4FD4-8208-5B7324A8F795"'
    Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Integer, ByVal hBitmap As Integer, ByVal nStartScan As Integer, ByVal nNumScans As Integer, ByRef lpBits As Object, ByRef lpBI As BITMAPINFO, ByVal wUsage As Integer) As Integer
	'UPGRADE_WARNING: Structure BITMAPINFO may require marshalling attributes to be passed as an argument in this Declare statement. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="C429C3A5-5D47-4CD9-8F51-74A1616405DC"'
	'UPGRADE_ISSUE: Declaring a parameter 'As Any' is not supported. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="FAE78A8D-8978-4FD4-8208-5B7324A8F795"'
    Private Declare Function SetDIBits Lib "gdi32" (ByVal hdc As Integer, ByVal hBitmap As Integer, ByVal nStartScan As Integer, ByVal nNumScans As Integer, ByRef lpBits As Object, ByRef lpBI As BITMAPINFO, ByVal wUsage As Integer) As Integer
	
    Dim LookUp(1, 1) As Integer
	
    Dim SourcePixels(1, 1, 1) As Byte
    Dim BackgroundPixels(1, 1, 1) As Byte
	'   Dim TimeStart As Long
	'   Dim TimeEnd As Long
	
	
	Public Sub ChromaKey() 'This is called when the chroma keying button is pressed on the main buttons form
		If ChromaKeyingYesNO = False Then 'The form cannot be activated if chromakeying is not activated in the settings window
			frmAnimator.Width = VB6.TwipsToPixelsX(500 * VB6.TwipsPerPixelX) 'Contract the button form to hide the chroma key slider controls
			Exit Sub
		End If
		
		Fiddle = 10
		If VB6.PixelsToTwipsX(frmAnimator.Width) < 750 * VB6.TwipsPerPixelX Then 'Check if the animator form is narrow
			Call PositionChromaSlider(1, (frmAnimator.picThreashold), Threashold, 510)
			Call PositionChromaSlider(1, (frmAnimator.picFeather), Feather, 150)
			Call PositionChromaSlider(1, (frmAnimator.picWhiteLimit), WhiteLimit, 255)
			Call PositionChromaSlider(1, (frmAnimator.picBlackLimit), BlackLimit, 255)
			
			frmAnimator.Width = VB6.TwipsToPixelsX(750 * VB6.TwipsPerPixelX) 'Expand the button form width to show the chroma key slider controls
			' ChromaKeyingYesNO = True                               'Turn ChromaKeying on
		Else
			frmAnimator.Width = VB6.TwipsToPixelsX(500 * VB6.TwipsPerPixelX) 'Contract the button form to hide the chroma key slider controls
			' ChromaKeyingYesNO = False                              'Turn Chroma Keying off
		End If
		
	End Sub
	
	Public Sub ActionChromaKeying(ByRef TargetPicture As System.Windows.Forms.PictureBox) 'This is called each program cycle (see  GetImageFromCamera on frmanimator)
		If ChromaKeyingYesNO = False Then Exit Sub 'Exit subroutine if chroma keying is off
		If ActiveWindowIs <> "ButtonWindow" Then Exit Sub 'Chroma keying is only active in button form, not editor or settings etc.
		If WindowAtFront <> "Live" Then Exit Sub 'Chroma Keying is only active in live mode
		
		Call ActionChromaSliders() 'Check if the sliders are being pressed
		
		
		
		frmAnimator.lblTH.Text = "TH = " & Threashold
		frmAnimator.lblFE.Text = "FE = " & Feather
		frmAnimator.lblWH.Text = "WH = " & WhiteLimit
		frmAnimator.lblBL.Text = "BL = " & BlackLimit
		
		If Rendering = True Then Exit Sub 'if the program is already rendering, dont try to render again
		Rendering = True
		
		Call FillLookUpTable(Threashold, Feather)
		Call PrepareBitmapInfo(TargetPicture)

        Dim backGraph As Graphics = frmAveraging.picBackground.CreateGraphics
        Dim backHDC As IntPtr = backGraph.GetHdc

        Dim targetGraph As Graphics = TargetPicture.CreateGraphics
        Dim targetHDC As IntPtr = targetGraph.GetHdc

		'Load the backgroundbitmap's data. This only needs doing once as background is static, foreground may change each frame
		'UPGRADE_WARNING: Lower bound of array BackgroundPixels was changed from 1,1,1 to 0,0,0. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="0F1C9BE1-AF9D-476E-83B1-17D43BECFF20"'
		ReDim BackgroundPixels(4, frmAveraging.picBackground.ClientRectangle.Width, frmAveraging.picBackground.ClientRectangle.Height)
		'UPGRADE_ISSUE: PictureBox property picBackground.Image was not upgraded. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="CC4C7EC0-C903-48FC-ACCC-81861D12DA4A"'
		'UPGRADE_ISSUE: PictureBox property picBackground.hdc was not upgraded. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="CC4C7EC0-C903-48FC-ACCC-81861D12DA4A"'
        GetDIBits(backHDC, CInt(CObj(frmAveraging.picBackground.Image)), 0, frmAveraging.picBackground.ClientRectangle.Height, BackgroundPixels(1, 1, 1), bitmap_info, 0)
		
		' Load the sourcebitmap's data.
		'UPGRADE_WARNING: Lower bound of array SourcePixels was changed from 1,1,1 to 0,0,0. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="0F1C9BE1-AF9D-476E-83B1-17D43BECFF20"'
		ReDim SourcePixels(4, VB6.PixelsToTwipsX(TargetPicture.ClientRectangle.Width), VB6.PixelsToTwipsY(TargetPicture.ClientRectangle.Height))
		'UPGRADE_ISSUE: PictureBox property TargetPicture.Image was not upgraded. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="CC4C7EC0-C903-48FC-ACCC-81861D12DA4A"'
		'UPGRADE_ISSUE: PictureBox property TargetPicture.hdc was not upgraded. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="CC4C7EC0-C903-48FC-ACCC-81861D12DA4A"'
        GetDIBits(targetHDC, CInt(CObj(TargetPicture.Image)), 0, VB6.PixelsToTwipsY(TargetPicture.ClientRectangle.Height), SourcePixels(1, 1, 1), bitmap_info, 0)
		
		If ChromaType = "Green" Then
			Call CalculatePixels_Green(TargetPicture)
		End If
		
		If ChromaType = "Blue" = True Then
			Call CalculatePixels_Blue(TargetPicture)
		End If
		
		If ChromaType = "Red" = True Then
			Call CalculatePixels_Red(TargetPicture)
		End If
		
		' Display the result.
		'UPGRADE_ISSUE: PictureBox property TargetPicture.Image was not upgraded. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="CC4C7EC0-C903-48FC-ACCC-81861D12DA4A"'
		'UPGRADE_ISSUE: PictureBox property TargetPicture.hdc was not upgraded. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="CC4C7EC0-C903-48FC-ACCC-81861D12DA4A"'
        SetDIBits(targetHDC, CInt(CObj(TargetPicture.Image)), 0, VB6.PixelsToTwipsY(TargetPicture.ClientRectangle.Height), SourcePixels(1, 1, 1), bitmap_info, 0)
		'UPGRADE_ISSUE: PictureBox property TargetPicture.Image was not upgraded. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="CC4C7EC0-C903-48FC-ACCC-81861D12DA4A"'
		TargetPicture.Image = TargetPicture.Image
		
        backGraph.ReleaseHdc(backHDC)
        backGraph.Dispose()

        targetGraph.ReleaseHdc(targetHDC)
        targetGraph.Dispose()

		
		Rendering = False
		
	End Sub
	
	Private Sub PositionChromaSlider(ByRef Mode As Short, ByRef TargetSlider As System.Windows.Forms.PictureBox, ByRef CurrentSliderValue As Integer, ByRef MaxSliderValue As Integer)
		'Position a Slider correctly given the target picturebox, the value required and the maximum allowable value of the slider
		
		Dim NewSliderPos As Integer
		' This command can be called in two modes
		'Mode 1 - It calculates the slider position from a supplied value
		'Mode 2 - It calculates it from the position of the cursor over the slider
		
		If Mode = 1 Then 'Calculate the slider position relative to the current position supplied
			NewSliderPos = CInt((CDbl(CurrentSliderValue) / CDbl(MaxSliderValue)) * VB6.PixelsToTwipsX(TargetSlider.Width)) 'calculate the slider position
		End If
		
		If Mode = 2 Then 'Calculate the slider position using the cursor position
			NewSliderPos = MousePoint.X
		End If
		
		If NewSliderPos < 3 Then NewSliderPos = 3 'Limit the display of the slider so it doesnt go over the end
		If NewSliderPos > VB6.PixelsToTwipsX(TargetSlider.Width) - 3 Then NewSliderPos = VB6.PixelsToTwipsX(TargetSlider.Width) - 3 'Limit the display of the slider so it doesnt go over the end

        Const vbSrcCopy As Integer = &HCC0020

        Dim targetGraph As Graphics = TargetSlider.CreateGraphics
        Dim targetHDC As IntPtr = targetGraph.GetHdc

        Dim sliderGraph As Graphics = frmAveraging.picSlider.CreateGraphics
        Dim sliderHDC As IntPtr = sliderGraph.GetHdc

		'UPGRADE_ISSUE: Constant vbWhiteness was not upgraded. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="55B59875-9A95-4B71-9D6A-7C294BF7139D"'
		'UPGRADE_ISSUE: PictureBox property TargetSlider.hdc was not upgraded. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="CC4C7EC0-C903-48FC-ACCC-81861D12DA4A"'
        Call BitBlt(targetHDC, 0, 0, VB6.PixelsToTwipsX(TargetSlider.Width), VB6.PixelsToTwipsY(TargetSlider.Height), 0, 0, 0, vbWhiteness) 'overwite the slider to erase the previous position
		'UPGRADE_ISSUE: Constant vbSrcCopy was not upgraded. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="55B59875-9A95-4B71-9D6A-7C294BF7139D"'
		'UPGRADE_ISSUE: PictureBox property picSlider.hdc was not upgraded. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="CC4C7EC0-C903-48FC-ACCC-81861D12DA4A"'
		'UPGRADE_ISSUE: PictureBox property TargetSlider.hdc was not upgraded. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="CC4C7EC0-C903-48FC-ACCC-81861D12DA4A"'
        Call BitBlt(targetHDC, NewSliderPos - 3, 1, 6, 13, sliderHDC, 0, 0, vbSrcCopy) 'blit the slider to the screen
        TargetSlider.Refresh() 'Refresh the slider control to show the changes

        targetGraph.ReleaseHdc(targetHDC)
        targetGraph.Dispose()

        sliderGraph.ReleaseHdc(sliderHDC)
        sliderGraph.Dispose()
		
	End Sub
	Private Sub ActionChromaSliders()
		'Now action all the sliders
		
		
		If GetAsyncKeyState(VK_LBUTTON) Then 'Check the Left mouse is being pressed
			
			'Threashold Slider
			Call GetCursorPos(MousePoint) 'Get the screen position of the cursor
			Call ScreenToClient(frmAnimator.picThreashold.Handle.ToInt32, MousePoint) 'Modify values so they are relative to top left of slider picture window
			If MousePoint.X > 0 And MousePoint.X < frmAnimator.picThreashold.Width Then 'check if we are over the slider picturebox
				If MousePoint.Y > 0 And MousePoint.Y < frmAnimator.picThreashold.Height Then
					Call PositionChromaSlider(2, (frmAnimator.picThreashold), -999, -999)
					'We know how far we are along the picturebox (mouse.x) and we know the width, so calculate the percentage along (value 0 to 1)
					'multiply this by the maximum threashold value to get the new value for the threashold
					Threashold = (((MousePoint.X) / frmAnimator.picThreashold.Width) * (510 + Fiddle)) - (Fiddle / 2)
					If Threashold < 0 Then Threashold = 0 'check we havent calculated it out of the boundary limits
					If Threashold > 510 Then Threashold = 510
					Call FillLookUpTable(Threashold, Feather)
					Exit Sub
				End If
			End If
			
			'Feather Slider
			Call GetCursorPos(MousePoint) 'Get the screen position of the cursor
			Call ScreenToClient(frmAnimator.picFeather.Handle.ToInt32, MousePoint) 'Modify values so they are relative to top left of slider picture window
			If MousePoint.X > 0 And MousePoint.X < frmAnimator.picFeather.Width Then 'check if we are over the slider picturebox
				If MousePoint.Y > 0 And MousePoint.Y < frmAnimator.picFeather.Height Then
					Call PositionChromaSlider(2, (frmAnimator.picFeather), -999, -999)
					'We know how far we are along the picturebox (mouse.x) and we know the width, so calculate the percentage along (value 0 to 1)
					'multiply this by the maximum threashold value to get the new value for the threashold
					Feather = (((MousePoint.X) / frmAnimator.picFeather.Width) * (255 + Fiddle)) - (Fiddle / 2)
					If Feather < 0 Then Feather = 0 'check we havent calculated it out of the boundary limits
					If Feather > 255 Then Feather = 255
					Call FillLookUpTable(Threashold, Feather)
					Exit Sub
				End If
			End If
			
			'WhiteLimit Slider
			Call GetCursorPos(MousePoint) 'Get the screen position of the cursor
			Call ScreenToClient(frmAnimator.picWhiteLimit.Handle.ToInt32, MousePoint) 'Modify values so they are relative to top left of slider picture window
			If MousePoint.X > 0 And MousePoint.X < frmAnimator.picWhiteLimit.Width Then 'check if we are over the slider picturebox
				If MousePoint.Y > 0 And MousePoint.Y < frmAnimator.picWhiteLimit.Height Then
					Call PositionChromaSlider(2, (frmAnimator.picWhiteLimit), -999, -999)
					'We know how far we are along the picturebox (mouse.x) and we know the width, so calculate the percentage along (value 0 to 1)
					'multiply this by the maximum threashold value to get the new value for the threashold
					WhiteLimit = (((MousePoint.X) / frmAnimator.picWhiteLimit.Width) * (255 + Fiddle)) - (Fiddle / 2)
					If WhiteLimit < 0 Then WhiteLimit = 0 'check we havent calculated it out of the boundary limits
					If WhiteLimit > 255 Then WhiteLimit = 255
					Exit Sub
				End If
			End If
			
			'BlackLimit Slider
			Call GetCursorPos(MousePoint) 'Get the screen position of the cursor
			Call ScreenToClient(frmAnimator.picBlackLimit.Handle.ToInt32, MousePoint) 'Modify values so they are relative to top left of slider picture window
			If MousePoint.X > 0 And MousePoint.X < frmAnimator.picBlackLimit.Width Then 'check if we are over the slider picturebox
				If MousePoint.Y > 0 And MousePoint.Y < frmAnimator.picBlackLimit.Height Then
					Call PositionChromaSlider(2, (frmAnimator.picBlackLimit), -999, -999)
					'We know how far we are along the picturebox (mouse.x) and we know the width, so calculate the percentage along (value 0 to 1)
					'multiply this by the maximum threashold value to get the new value for the threashold
					BlackLimit = (((MousePoint.X) / frmAnimator.picBlackLimit.Width) * (255 + Fiddle)) - (Fiddle / 2)
					If BlackLimit < 0 Then BlackLimit = 0 'check we havent calculated it out of the boundary limits
					If BlackLimit > 255 Then BlackLimit = 255
					Exit Sub
				End If
			End If
		End If
	End Sub
	
	Public Sub FillLookUpTable(ByRef Threashold As Integer, ByRef Feather As Integer)
		Dim X As Integer
		Dim Y As Integer
		
		Dim Value1 As Integer
		Value1 = 255
		
		ReDim LookUp(511, 2) 'Resize (and clear) the lookup table (0 - 510)
		For X = 0 To Threashold
			If X > 510 Then GoTo CompletelyFilled
			LookUp(X, 0) = 255 '100% ie picture is opaque
			LookUp(X, 1) = 0 'Column stores the inverse of above, ie 0%
		Next X
		
		For X = Threashold + 1 To Threashold + Feather
			Value1 = Value1 - (255 / Feather)
			If Value1 < 0 Then Value1 = 0
			If X > 510 Then GoTo CompletelyFilled
			LookUp(X, 0) = Value1 'store the % value of slope
			LookUp(X, 1) = 255 - Value1 'Store the inverse value
		Next X
		
		For X = Threashold + Feather + 1 To 510
			If X > 510 Then GoTo CompletelyFilled
			LookUp(X, 0) = 0
			LookUp(X, 1) = 255
		Next X
CompletelyFilled: 
		
		
	End Sub
	Private Sub PrepareBitmapInfo(ByRef TargetPicture As System.Windows.Forms.PictureBox)
		' Prepare the bitmap description.
		Dim bytes_per_scanLine As Short
		Dim pad_per_scanLine As Short
		bitmap_info.bmiHeader.biSize = 40
		bitmap_info.bmiHeader.biWidth = VB6.PixelsToTwipsX(TargetPicture.ClientRectangle.Width)
		' Use negative height to scan top-down.
		bitmap_info.bmiHeader.biHeight = -VB6.PixelsToTwipsY(TargetPicture.ClientRectangle.Height)
		bitmap_info.bmiHeader.biPlanes = 1
		bitmap_info.bmiHeader.biBitCount = 32
		bitmap_info.bmiHeader.biCompression = 0
		bytes_per_scanLine = ((((bitmap_info.bmiHeader.biWidth * bitmap_info.bmiHeader.biBitCount) + 31) \ 32) * 4)
		pad_per_scanLine = bytes_per_scanLine - (((bitmap_info.bmiHeader.biWidth * bitmap_info.bmiHeader.biBitCount) + 7) \ 8)
		bitmap_info.bmiHeader.biSizeImage = bytes_per_scanLine * System.Math.Abs(bitmap_info.bmiHeader.biHeight)
	End Sub
	Private Sub CalculatePixels_Red(ByRef TargetPicture As System.Windows.Forms.PictureBox) '***********CURRENTLY AN ALTERNATIVE GREENSCREEN METHOD TO TEST SPEED********************
		Dim X As Integer
		Dim Y As Integer
		Dim d As Integer
		
		For Y = 1 To VB6.PixelsToTwipsY(TargetPicture.ClientRectangle.Height)
			For X = 1 To VB6.PixelsToTwipsX(TargetPicture.ClientRectangle.Width)
				Red_Source = (SourcePixels(3, X, Y)) : Green_Source = (SourcePixels(2, X, Y)) : Blue_Source = (SourcePixels(1, X, Y))
				d = (2 * Red_Source) - Green_Source - Blue_Source 'Calculate the deviation of the colour from the grey plane (see pdf for explaination)
				If d < Threashold Then GoTo NoAction : 'Quick check if its below threashold, its foreground, so dont do anything else.
				If (Green_Source > WhiteLimit) Or (Blue_Source > WhiteLimit) Then GoTo NoAction : 'd = 0           'if the colour is very light, consider it foreground.
				If Red_Source < BlackLimit Then GoTo NoAction : 'd = 0                                         'if the colour is very dark, consider it foreground.
				'If d is 0 the routine will plot the source. If d = 510 the routine will plot the background
				Alpha = LookUp(d, 0) : InvAlpha = LookUp(d, 1) 'Pass this through the lookuptable to return the alpha value
				'If alpha is 1 the routine will plot the source image. If alpha is 0 the routine will plot the background
				SourcePixels(3, X, Y) = CByte(((Red_Source * Alpha) + (BackgroundPixels(3, X, Y) * InvAlpha)) / 255)
				SourcePixels(2, X, Y) = CByte(((Green_Source * Alpha) + (BackgroundPixels(2, X, Y) * InvAlpha)) / 255)
				SourcePixels(1, X, Y) = CByte(((Blue_Source * Alpha) + (BackgroundPixels(1, X, Y) * InvAlpha)) / 255)
NoAction: 
			Next X
		Next Y
		
	End Sub
	Private Sub CalculatePixels_Green(ByRef TargetPicture As System.Windows.Forms.PictureBox)
		'TimeStart = timeGetTime
		Dim X As Integer
		Dim Y As Integer
		Dim d As Integer
		
		For Y = 1 To VB6.PixelsToTwipsY(TargetPicture.ClientRectangle.Height)
			For X = 1 To VB6.PixelsToTwipsX(TargetPicture.ClientRectangle.Width)
				Red_Source = (SourcePixels(3, X, Y)) : Green_Source = (SourcePixels(2, X, Y)) : Blue_Source = (SourcePixels(1, X, Y))
				d = (2 * Green_Source) - Red_Source - Blue_Source 'Calculate the deviation of the colour from the grey plane (see pdf for explaination)
				If d < Threashold Then GoTo NoAction : 'Quick check if its below threashold, its foreground, so dont do anything else.
				If (Red_Source > WhiteLimit) Or (Blue_Source > WhiteLimit) Then GoTo NoAction : 'd = 0           'if the colour is very light, consider it foreground.
				If Green_Source < BlackLimit Then GoTo NoAction : ' d = 0                                         'if the colour is very dark, consider it foreground.
				'If d is 0 the routine will plot the source. If d = 510 the routine will plot the background
				Alpha = LookUp(d, 0) : InvAlpha = LookUp(d, 1) 'Pass this through the lookuptable to return the alpha value
				'If alpha is 1 the routine will plot the source image. If alpha is 0 the routine will plot the background
				SourcePixels(3, X, Y) = CByte(((Red_Source * Alpha) + (BackgroundPixels(3, X, Y) * InvAlpha)) / 255)
				SourcePixels(2, X, Y) = CByte(((Green_Source * Alpha) + (BackgroundPixels(2, X, Y) * InvAlpha)) / 255)
				SourcePixels(1, X, Y) = CByte(((Blue_Source * Alpha) + (BackgroundPixels(1, X, Y) * InvAlpha)) / 255)
				
NoAction: 
			Next X
		Next Y
		
		' TimeEnd = timeGetTime
		' frmDiagnostics.Caption = "Diagnostics - Chroma Keying running at  " & (TimeEnd - TimeStart) & " milliseconds"
	End Sub
	
	Private Sub CalculatePixels_Blue(ByRef TargetPicture As System.Windows.Forms.PictureBox)
		Dim X As Integer
		Dim Y As Integer
		Dim d As Integer
		
		For Y = 1 To VB6.PixelsToTwipsY(TargetPicture.ClientRectangle.Height)
			For X = 1 To VB6.PixelsToTwipsX(TargetPicture.ClientRectangle.Width)
				Red_Source = (SourcePixels(3, X, Y)) : Green_Source = (SourcePixels(2, X, Y)) : Blue_Source = (SourcePixels(1, X, Y))
				d = (2 * Blue_Source) - Red_Source - Green_Source 'Calculate the deviation of the colour from the grey plane (see pdf for explaination)
				If d < Threashold Then GoTo NoAction : 'Quick check if its below threashold, its foreground, so dont do anything else.
				If (Red_Source > WhiteLimit) Or (Green_Source > WhiteLimit) Then GoTo NoAction : 'd = 0           'if the colour is very light, consider it foreground.
				If Blue_Source < BlackLimit Then GoTo NoAction : 'd = 0                                         'if the colour is very dark, consider it foreground.
				'If d is 0 the routine will plot the source. If d = 510 the routine will plot the background
				Alpha = LookUp(d, 0) : InvAlpha = LookUp(d, 1) 'Pass this through the lookuptable to return the alpha value
				'If alpha is 1 the routine will plot the source image. If alpha is 0 the routine will plot the background
				SourcePixels(3, X, Y) = CByte(((Red_Source * Alpha) + (BackgroundPixels(3, X, Y) * InvAlpha)) / 255)
				SourcePixels(2, X, Y) = CByte(((Green_Source * Alpha) + (BackgroundPixels(2, X, Y) * InvAlpha)) / 255)
				SourcePixels(1, X, Y) = CByte(((Blue_Source * Alpha) + (BackgroundPixels(1, X, Y) * InvAlpha)) / 255)
NoAction: 
			Next X
		Next Y
		
	End Sub
End Module